﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reactive;
using System.Reactive.Linq;
using System.Threading.Tasks;
using ManagerClient.AuthentificationService;
using ManagerClient.Manage.Views;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Unity;

namespace ManagerClient.Manage.Logic
{
    public class ManageMenuViewModel : TabPageViewModelBase
    {
        #region Delegates

        public delegate void Add();

        #endregion

        private readonly AuthentificationServiceClient client;
        private readonly IUnityContainer container;
        private readonly List<Dish> newItems;
        private ObservableCollection<Dish> menu;
        private IEnumerable<Dish> selectedMenuItems;

        public ManageMenuViewModel(AuthentificationServiceClient client, IUnityContainer container)
        {
            Title = "Управление меню";
            this.container = container;
            this.client = client;
            IsBusy = true;
            selectedMenuItems = new List<Dish>();
            newItems = new List<Dish>();
            SynchronizeDataCommand = new DelegateCommand(OnSaveItem);
            LoadDataFromService();
            //IObservable<IEnumerable<Dish>> func = Observable.FromAsyncPattern<int, IEnumerable<Dish>>(
            //    client.BeginGetAllDishesForDepartment, client.EndGetAllDishesForDepartment)(1);
            //func.
            //    ObserveOnDispatcher().
            //    Finally(() => { IsBusy = false; }
            //    )
            //    .Subscribe(x => { menu = new ObservableCollection<Dish>(x); },
            //               e => { }
            //    );


            AddItemCommand = new DelegateCommand(AddItem);
            FormMenuCommand = new DelegateCommand(FormMenu);
        }


        public IEnumerable<Dish> SelectedMenuItems
        {
            get { return selectedMenuItems; }
            set
            {
                selectedMenuItems = value;
                RaisePropertyChanged(() => SelectedMenuItems);
            }
        }

        public DelegateCommand FormMenuCommand { get; set; }

        public ObservableCollection<Dish> Menu
        {
            get { return menu; }
            private set
            {
                menu = value;
                RaisePropertyChanged(() => Menu);
            }
        }

        public DelegateCommand AddItemCommand { get; set; }

        public DelegateCommand SynchronizeDataCommand { get; set; }

        private void LoadDataFromService()
        {
            Task<Dish[]> task = Task.Factory.FromAsync<int, Dish[]>(
                client.BeginGetAllDishesForDepartment,
                client.EndGetAllDishesForDepartment, 1, menu);

            Menu = new ObservableCollection<Dish>(task.Result);
        }

        private void GetMenuAsync()
        {
            IObservable<IEnumerable<Dish>> func = Observable.FromAsyncPattern<int, IEnumerable<Dish>>(
                client.BeginGetAllDishesForDepartment, client.EndGetAllDishesForDepartment)(1);
            func.
                ObserveOnDispatcher().
                Finally(() => { IsBusy = false; }
                )
                .Subscribe(x => { Menu = new ObservableCollection<Dish>(x); },
                           e => { }
                );
        }

        private void FormMenu()
        {
        }

        public void InitializeFields()
        {
        }

        public void OnSaveItem()
        {
            IObservable<Unit> func = Observable.FromAsyncPattern<Dish[], int>(
                client.BeginAddDishes, client.EndAddDishes)(newItems.ToArray(), 1);
            func.
                ObserveOnDispatcher().
                Finally(() => { IsBusy = false; }
                )
                .Subscribe(x => { GetMenuAsync(); },
                           e => { }
                );
        }

        private void AddItem()
        {
            var dialog = new CreateDishControl();
            var dialogVM = container.Resolve<CreateDishControlVM>();
            dialog.DataContext = dialogVM;
            dialog.Show();

            Observable.FromEventPattern<EventHandler<Saved>, Saved>(h => dialogVM.Saved += h,
                                                                    h => dialogVM.Saved -= h).
                       Take(1).
                       Where(ev =>
                             ev.EventArgs != null).
                       Subscribe(x =>
                           {
                               dialog.Close();
                               Menu.Add(x.EventArgs.Dish);
                               newItems.Add(x.EventArgs.Dish);
                           });
        }
    }
}